package com.innovation.ic.sc.base.service.sc.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.json.XML;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.innovation.ic.b1b.framework.util.HttpUtils;
import com.innovation.ic.b1b.framework.util.MiscUtil;
import com.innovation.ic.sc.base.handler.sc.AuthenticationUserHandler;
import com.innovation.ic.sc.base.mapper.sc.SmsInfoMapper;
import com.innovation.ic.sc.base.mapper.sc.UserMapper;
import com.innovation.ic.sc.base.model.sc.SmsInfo;
import com.innovation.ic.sc.base.pojo.constant.Constants;
import com.innovation.ic.sc.base.pojo.constant.LoginConstants;
import com.innovation.ic.sc.base.pojo.constant.SmsConstants;
import com.innovation.ic.sc.base.pojo.constant.handler.RedisStorage;
import com.innovation.ic.sc.base.pojo.variable.AuthenticationUser;
import com.innovation.ic.sc.base.pojo.variable.ServiceResult;
import com.innovation.ic.sc.base.pojo.enums.SmsStatusEnum;
import com.innovation.ic.sc.base.pojo.enums.SmsTemplateEnum;
import com.innovation.ic.sc.base.service.ServiceHelper;
import com.innovation.ic.sc.base.service.sc.SmsInfoService;
import com.innovation.ic.sc.base.value.ErpInterfaceAddressConfig;
import com.innovation.ic.sc.base.value.LoginConfig;
import com.innovation.ic.sc.base.value.RedisParamConfig;
import com.innovation.ic.sc.base.value.SmsParamConfig;
import com.innovation.ic.sc.base.vo.UsersVo;
import com.innovation.ic.sc.base.vo.cms.AccountBindBySmsVo;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;

/**
 * @desc   SmsInfoService的实现类
 * @author linuo
 * @time   2022年8月5日10:56:28
 */
@Service
@Transactional
public class SmsInfoServiceImpl extends ServiceImpl<SmsInfoMapper, SmsInfo> implements SmsInfoService {
    private static final Logger logger = LoggerFactory.getLogger(SmsInfoServiceImpl.class);

    @Resource
    private ServiceHelper serviceHelper;

    /**
     * 绑定账号
     * @param accountBindBySmsVo 账号绑定的Vo类
     * @return 返回绑定结果
     */
    @Override
    public ServiceResult<JSONObject> bindAccount(AccountBindBySmsVo accountBindBySmsVo) throws IOException {
        ServiceResult<JSONObject> serviceResult = new ServiceResult<>();
        JSONObject result = new JSONObject();
        Boolean success = Boolean.FALSE;
        String message = null;

        // 调用erp9接口进行登录操作
        JSONObject param = (JSONObject) JSON.toJSON(accountBindBySmsVo);
        String bandResult = HttpUtils.sendPost(serviceHelper.getErpInterfaceAddressConfig().getErpBindMobileByPwdUrl(), param.toString());
        if(bandResult != null){
            JSONObject parse = (JSONObject) JSONObject.parse(bandResult);
            if(parse != null){
                Integer status = parse.getInteger(LoginConstants.STATUS_FIELD);

                // 成功
                if(status == HttpStatus.SC_OK){
                    message = "绑定成功";
                    success = Boolean.TRUE;

                    // 调用ERP登录接口进行登录操作
                    JSONObject jsonObject = loginThroughErp(accountBindBySmsVo);
                    if(jsonObject != null){
                        result = jsonObject.getJSONObject(Constants.RESULT);
                    }else{
                        message = "绑定失败,请重试";
                        success = Boolean.FALSE;
                    }
                }

                // 将失败信息返回给前端响应
                if(status == HttpStatus.SC_INTERNAL_SERVER_ERROR){
                    message = "绑定失败,请重试";
                    String msg = parse.getString(LoginConstants.MSG);
                    if(!Strings.isNullOrEmpty(msg)){
                        message = msg;
                    }else{
                        message = parse.getString(LoginConstants.DATA);
                    }
                }
            }
        }

        serviceResult.setSuccess(success);
        serviceResult.setResult(result);
        serviceResult.setMessage(message);
        return serviceResult;
    }

    /**
     * 解绑账号
     * @param authenticationUser 登录用户
     * @return 返回解绑结果
     */
    @Override
    public ServiceResult<Boolean> unBindAccount(AuthenticationUser authenticationUser) {
        ServiceResult<Boolean> serviceResult = new ServiceResult<>();
        Boolean result = Boolean.FALSE;
        String message = null;

        String bandResult = HttpUtils.erpSendPost(serviceHelper.getErpInterfaceAddressConfig().getErpUnBindUrl(), null, authenticationUser.getToken());
        if(!Strings.isNullOrEmpty(bandResult)){
            JSONObject parse = (JSONObject) JSONObject.parse(bandResult);
            if(parse != null){
                Integer status = parse.getInteger(LoginConstants.STATUS_FIELD);

                // 成功
                if(status == HttpStatus.SC_OK){
                    message = "解绑成功";
                    result = Boolean.TRUE;
                }else{
                    String msg = parse.getString(LoginConstants.MSG);
                    if(!Strings.isNullOrEmpty(msg)){
                        message = msg;
                    }else{
                        message = parse.getString(LoginConstants.DATA);
                    }

                    if(!Strings.isNullOrEmpty(message)){
                        message = "解绑成功,请重试";
                    }
                }
            }
        }

        serviceResult.setSuccess(result);
        serviceResult.setResult(result);
        serviceResult.setMessage(message);
        return serviceResult;
    }

    /**
     * 通过ERP发送短信验证码
     * @param mobile 手机号
     * @return 返回发送结果
     */
    @Override
    public ServiceResult<JSONObject> sendSmsCodeByErp(String mobile) {
        ServiceResult<JSONObject> serviceResult = new ServiceResult<>();
        Boolean result = Boolean.FALSE;
        String message = null;
        Integer code = null;

        // 发送短信参数
        String param = SmsConstants.PHONE_FIELD + LoginConstants.EQUAL_SIGN + mobile;

        // 通过ERP发送短信验证码
        String sendResult = HttpUtils.sendGet(serviceHelper.getSmsParamConfig().getErpSendSmsUrl(), param, null);
        if(!Strings.isNullOrEmpty(sendResult)) {
            JSONObject json = (JSONObject) JSONObject.parse(sendResult);
            if(json != null){
                Integer status = json.getInteger(LoginConstants.STATUS_FIELD);
                if(status == HttpStatus.SC_OK){
                    message = "短信发送成功";
                    logger.info(message);
                    result = Boolean.TRUE;
                    code = json.getInteger(LoginConstants.DATA);
                }
                if(status == HttpStatus.SC_INTERNAL_SERVER_ERROR){
                    message = json.getString(LoginConstants.MSG);
                    logger.info(message);
                    result = Boolean.FALSE;
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(Constants.RESULT, result);
                    serviceResult.setSuccess(result);
                    serviceResult.setMessage(message);
                    return serviceResult;
                }
            }
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put(Constants.RESULT, result);
        jsonObject.put(LoginConstants.CODE_FIELD, code);

        serviceResult.setSuccess(result);
        serviceResult.setResult(jsonObject);
        serviceResult.setMessage(message);
        return serviceResult;
    }

    /**
     * 发送短信验证码
     * @param type   短信验证码类型,1: 登录
     * @param mobile 手机号
     * @return 返回发送短信验证码结果
     */
    @Override
    public ServiceResult<Boolean> send(String type, String mobile) {
        ServiceResult<Boolean> serviceResult = new ServiceResult<>();
        Boolean result = Boolean.FALSE;
        String message = null;

        try {
            // 生成随机短信验证码
            String smsCode = MiscUtil.randomNum(serviceHelper.getSmsParamConfig().getLength(), "SHA1PRNG");

            // 发送短信
            String sendMsgResult;
            String smsTemplate = SmsTemplateEnum.getDesc(type);
            smsTemplate = smsTemplate.replace(SmsConstants.SMS_CODE, smsCode);
            logger.info("发送给手机:[{}]的短信内容为:[{}]", mobile, smsTemplate);
            if(serviceHelper.getSmsParamConfig().getEnable()){
                sendMsgResult = sendMsg(mobile, smsTemplate);
            }else{
                sendMsgResult = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CSubmitState xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://tempuri.org/\">  <State>0</State>  <MsgID>2208051555129749833</MsgID>  <MsgState>提交成功</MsgState>  <Reserve>1</Reserve></CSubmitState>\n" +
                        "<?xml version=\"1.0\" encoding=\"utf-8\"?><CSubmitState xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://tempuri.org/\">  <State>0</State>  <MsgID>2208051555129749833</MsgID>  <MsgState>提交成功</MsgState>  <Reserve>1</Reserve></CSubmitState>";
            }
            cn.hutool.json.JSONObject json = XML.toJSONObject(sendMsgResult);
            logger.info("短信发送结果为[{}]" + json.toString());
            if(json.get(SmsConstants.SMS_SUBMIT_STATE) != null){
                JSONArray jsonArray = (JSONArray) json.get(SmsConstants.SMS_SUBMIT_STATE);
                if(jsonArray != null && jsonArray.size() > 0){
                    JSONObject stateJson = (JSONObject) jsonArray.get(0);
                    if(stateJson != null && stateJson.get(SmsConstants.STATE) != null){
                        Integer state = (Integer) stateJson.get(SmsConstants.STATE);
                        if(state == 0){
                            message = "短信发送成功";
                            logger.info(message);
                            result = Boolean.TRUE;

                            // 向数据库中插入短信发送信息
                            insertSmsInfoData(type, mobile, smsCode);
                        }
                    }
                }
            }
        }catch (Exception e){
            logger.info("发送短信验证码功能出现问题,原因:", e);
            message = "验证码发送失败,请重试";
        }

        serviceResult.setSuccess(result);
        serviceResult.setResult(result);
        serviceResult.setMessage(message);
        return serviceResult;
    }

    /**
     * 向数据库中插入短信发送信息
     */
    private void insertSmsInfoData(String type, String mobile, String smsCode) {
        SmsInfo smsInfo = new SmsInfo();
        //smsInfo.setId(IdUtils.getIdByPkName(SmsConstants.SMS_PK_NAME));
        smsInfo.setMobile(mobile);
        smsInfo.setType(type);
        smsInfo.setSmsCode(smsCode);
        smsInfo.setCreateTime(new Date(System.currentTimeMillis()));
        smsInfo.setVerifyTimes(0);
        smsInfo.setSmsStatus(SmsStatusEnum.READY.getCode());
        serviceHelper.getSmsInfoMapper().insert(smsInfo);
    }

    /**
     * 发送短信
     * @param mobile 手机号
     * @param msg 短信内容
     * @return 发送短息发送结果
     */
    private String sendMsg(String mobile, String msg){
        String name = serviceHelper.getSmsParamConfig().getName();
        String password = serviceHelper.getSmsParamConfig().getPassword();
        String smsCode = serviceHelper.getSmsParamConfig().getSmsCode();

        String param = SmsConstants.SMS_NAME + "=" + name +
                "&" + SmsConstants.SMS_PWD + "=" + password +
                "&" + SmsConstants.SMS_SCORPID + "=" + "" +
                "&" + SmsConstants.SMS_SPRDID + "=" + smsCode +
                "&" + SmsConstants.SMS_MOBILE + "=" + mobile +
                "&" + SmsConstants.SMS_MSG + "=" + msg;
        return HttpUtils.sendGet(serviceHelper.getSmsParamConfig().getUrl(), param, null);
    }

    /**
     * 调用ERP登录接口进行登录操作
     * @param accountBindBySmsVo 账号绑定的Vo类
     * @return 返回登录用户信息
     */
    private JSONObject loginThroughErp(AccountBindBySmsVo accountBindBySmsVo) throws IOException {
        UsersVo usersVo = new UsersVo();
        usersVo.setUserName(accountBindBySmsVo.getUserName());
        usersVo.setPassword(accountBindBySmsVo.getPassWord());
        String result = HttpUtils.doPostTestTwo(serviceHelper.getLoginConfig().getUrl(), JSON.toJSONString(usersVo));
        if(!Strings.isNullOrEmpty(result)) {
            JSONObject json = (JSONObject) JSONObject.parse(result);
            Integer status = json.getInteger(LoginConstants.STATUS_FIELD);
            // 成功
            if(status == HttpStatus.SC_OK) {
                JSONObject jsonObject = new JSONObject();
                JSONObject data = (JSONObject) json.get(LoginConstants.DATA);
                if (data != null) {
                    String token = (String) data.get(LoginConstants.TOKEN);
                    // 将token对象转换为接收用户信息vo类对象
                    AuthenticationUser authenticationUser = AuthenticationUserHandler.toAuthenticationUser(token);
                    if (authenticationUser != null) {

                        // 将用户信息存储到redis中
                        this.setAuthenticationUser(authenticationUser);

                        // 查询账号评分
                        Float score = serviceHelper.getUserMapper().getScoreById(authenticationUser.getId());
                        if(score == null){
                            score = 0F;
                        }
                        authenticationUser.setScore(score);
                        jsonObject.put(Constants.RESULT, JSON.toJSON(authenticationUser));
                    }
                    jsonObject.put(LoginConstants.STATUS_FIELD, status);
                }
                return jsonObject;
            }
        }
        return null;
    }

    /**
     * 将AuthenticationUser对象存储到redis中，key为token，value是json字符串
     * @param authenticationUser 接收用户信息vo类
     */
    private void setAuthenticationUser(AuthenticationUser authenticationUser) {
        serviceHelper.getRedisManager().set(RedisStorage.TOKEN_PREFIX + authenticationUser.getToken(), JSON.toJSONString(authenticationUser));
        serviceHelper.getRedisManager().expire(RedisStorage.TOKEN_PREFIX + authenticationUser.getToken(), serviceHelper.getRedisParamConfig().getTokenTimeout());
    }
}